package uu.game.majiang.core.rule.paixing.gb;

import java.util.ArrayList;

import uu.game.majiang.core.Pai;
import uu.game.majiang.core.Pai.Hupai;
import uu.game.majiang.core.rule.paixing.HuPaixing;
import uu.game.majiang.core.rule.paixing.PaixingAnalyser;

/**
 * 国标牌型解析器
 * 
 * @author uu
 * @see GbPaixing
 * @see PaixingAnalyser
 * @see Pai
 * @version 2010-5-8 上午09:30:05
 */
public class GbPaixingAnalyser implements PaixingAnalyser {
    
    @Override
    public HuPaixing[] analyse(Hupai hupai) {
        ArrayList<HuPaixing> list = new ArrayList<HuPaixing>();
        GbPaixing[] toMatch;
        HuPaixing[] hps = hupai.getHuPaixings();
        if (hps.length != 0 && hps[0].paixing.isSpecial()) {
            list.add(hps[0]);
            toMatch = ((GbPaixing)hps[0].paixing).next();
        } else {
            toMatch = GbPaixing.values();
        }
        analyse1(list, toMatch, hupai);
        return list.toArray(new HuPaixing[list.size()]);
    }
    
    @Override
    public HuPaixing isSpecialPaixing(Hupai hupai) {
        GbPaixing[] specials = GbPaixing.getSpecials();
        for (int i = 0; i < specials.length; i++) {
            GbPaixing px = specials[i];
            int count = px.match(hupai);
            if (count != 0)
                return new HuPaixing(px, count);
        }
        return null;
    }
    
    private void analyse1(ArrayList<HuPaixing> list, GbPaixing[] toMatch, Hupai hupai) {
        next: while (toMatch != null && toMatch.length != 0) {
            for (int i = 0; i < toMatch.length; i++) {
                GbPaixing px = toMatch[i];
                int count = px.match(hupai);
                if (count != 0) {
                    list.add(new HuPaixing(px, count));
                    toMatch = interception(toMatch, i + 1, px.next(), 0);
                    // TODO 测试一下，直接toMatch = px.next()快还是求交集以后判断快
                    continue next;
                }
            }
            return;
        }
    }
    
    /*
     * 得到两个牌型数组的交集
     */
    private GbPaixing[] interception(GbPaixing[] a1, int from1, GbPaixing[] a2, int from2) {
        int l1 = a1.length;
        int l2 = a2.length;
        if (l1 - from1 <= 0 || l2 - from2 <= 0 || a1[l1 - 1].compareTo(a2[from2]) < 0
                || a1[from1].compareTo(a2[l2 - 1]) > 0)
            return new GbPaixing[0];
        int i1 = from1;
        int i2 = from2;
        GbPaixing e1;
        GbPaixing e2;
        int l = 0;
        while (i1 < l1 && i2 < l2) {
            e1 = a1[i1];
            e2 = a2[i2];
            if (e1.compareTo(e2) < 0)
                i1++;
            else if (e1.compareTo(e2) > 0)
                i2++;
            else {
                l++;
                i1++;
                i2++;
            }
        }
        GbPaixing[] a = new GbPaixing[l];
        int i = 0;
        i1 = from1;
        i2 = from2;
        while (i < l) {
            e1 = a1[i1];
            e2 = a2[i2];
            if (e1.compareTo(e2) < 0)
                i1++;
            else if (e1.compareTo(e2) > 0)
                i2++;
            else {
                a[i++] = e1;
                i1++;
                i2++;
            }
        }
        return a;
    }
    
}
